package com.retail.core.config;


import cn.hutool.core.util.ArrayUtil;
import com.fasterxml.jackson.databind.introspect.AnnotatedField;
import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
import com.google.common.base.Optional;
import io.swagger.annotations.ApiModelProperty;
import org.springframework.stereotype.Component;
import springfox.documentation.schema.Annotations;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.schema.ModelPropertyBuilderPlugin;
import springfox.documentation.spi.schema.contexts.ModelPropertyContext;
import springfox.documentation.swagger.common.SwaggerPluginSupport;
import springfox.documentation.swagger.schema.ApiModelProperties;

import java.lang.reflect.Field;


/**
 * swagger 请求响应参数中属性按照字段定义顺序排列，不要按照字母顺序排列
 */
@Component
public class CustomApiModelPropertyPositionBuilder implements ModelPropertyBuilderPlugin {
	
	@Override
	public boolean supports(DocumentationType delimiter) {
		return SwaggerPluginSupport.pluginDoesApply(delimiter);
	}
	
	
	@Override
	public void apply(ModelPropertyContext context) {
		Optional<BeanPropertyDefinition> beanPropertyDefinitionOpt = context.getBeanPropertyDefinition();
		Optional<ApiModelProperty> annotation = Optional.absent();
		if (context.getAnnotatedElement().isPresent()) {
			annotation = annotation.or(ApiModelProperties.findApiModePropertyAnnotation(context.getAnnotatedElement().get()));
		}
		if (context.getBeanPropertyDefinition().isPresent()) {
			annotation = annotation.or(Annotations.findPropertyAnnotation(context.getBeanPropertyDefinition().get(), ApiModelProperty.class));
		}
		//必须是有ApiModelProperty注解的字段，并且beanPropertyDefinitionOpt带有注解
		if (annotation.isPresent() && beanPropertyDefinitionOpt.isPresent()) {
			BeanPropertyDefinition beanPropertyDefinition = beanPropertyDefinitionOpt.get();
			
			//获取到注解字段
			AnnotatedField field = beanPropertyDefinition.getField();
			//获取到字段所在的类
			Class<?> clazz = field.getDeclaringClass();
			//获取类中所有字段
			Field[] declaredFields = clazz.getDeclaredFields();
			Field declaredField;//获取当前字段的Field
			
			try {
				declaredField = clazz.getDeclaredField(field.getName());
			} catch (NoSuchFieldException | SecurityException e) {
				return;
			}
			
			//获取当前字段在数组中的位置。然后设置position属性
			int indexOf = ArrayUtil.indexOf(declaredFields, declaredField);
			if (indexOf != -1) {
				context.getBuilder().position(indexOf);
			}
		}
	}
}
